package com.tqjc.business.interactivewithscan.core.thread.tanker;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tqjc.business.interactivewithscan.consts.CoordConstant;
import com.tqjc.business.interactivewithscan.consts.DeviceEnum;
import com.tqjc.business.interactivewithscan.consts.ExceptionEnum;
import com.tqjc.business.interactivewithscan.core.data.AskData.AskData;
import com.tqjc.business.interactivewithscan.core.data.PointData.PointData;
import com.tqjc.business.interactivewithscan.core.thread.NormalThread;
import com.tqjc.business.interactivewithscan.core.thread.PTZ.DoubleTrackPZTThread;
import com.tqjc.business.interactivewithscan.entity.*;
import com.tqjc.business.interactivewithscan.exception.CustomException;
import com.tqjc.business.interactivewithscan.service.MaterialInfoService;
import com.tqjc.business.interactivewithscan.service.ScanDeviceDataService;
import com.tqjc.business.interactivewithscan.service.UfcDeviceInfoService;
import com.tqjc.business.interactivewithscan.service.impl.ScanDeviceDataServiceImpl;
import com.tqjc.business.interactivewithscan.uils.CommonUtils;
import com.tqjc.business.interactivewithscan.uils.CoordinatesUtils;
import com.tqjc.business.interactivewithscan.uils.PTZUtils;
import com.tqjc.system.core.util.SpringUtils;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @program: C20005_Xianggang_new
 * @description: 双轨槽车扫描类
 * @author: Patienyon
 * @create: 2023-12-19 15:48
 **/
//@Component("DoubleTankerScanThread")
@Slf4j
public class DoubleTankerScanThread extends NormalThread {

    private ReentrantLock lock = new ReentrantLock();


    public volatile Queue<AskData> askDataQue = new LinkedBlockingQueue<>();

    public volatile Map<String, PointData> responseMap = new LinkedHashMap<>();

    private static final ScanDeviceData firstTanker = SpringUtils.getBean(ScanDeviceDataService.class).getById(100010);
    private static final ScanDeviceData secondTanker = SpringUtils.getBean(ScanDeviceDataService.class).getById(100009);

    //设置槽车和设备的绑定
    static Map<String, String> deviceCodeIdMap = new HashMap() {{
        put("400002", "100009");
        put("400001", "100010");
        put("400004", "100011");
        put("400003", "100008");

    }};

    //定义天车对应ID
    static Map<Integer, String> craneIdMap = new HashMap() {{
        //废钢1号
        put(1, "100004");
        //废钢2号
        put(2, "100005");
        //炉渣一号
        put(3, "100006");
        //炉渣二号
        put(4, "100007");

    }};
    @Resource
    UfcDeviceInfoService ufcDeviceInfoService;


    /**
     * 物料信息
     */
    @Resource
    MaterialInfoService materialInfoService;
//    private static BMaterialService materialService = ApplicationContextUtil.getBean(BMaterialService.class);
//    private static MaterialInfoService materialService = ApplicationContextUtil.getBean(BMaterialService.class);
    /**
     * 设备信息
     */
    @Resource
    private UfcDeviceInfoService deviceInfoService;

    /**
     * 当前所属跨
     * 100：指定废钢跨，200：指定炉渣跨，000:转炉
     */
    @Getter
    private String span = "200";

    private Coord old;

    private ScanningData scanningData;

    public void setSpan(String span) {
        this.span = span;
    }

    public void setScanningData(ScanningData scanningData) {
        this.scanningData = scanningData;
        this.old = null;
    }


    public DoubleTankerScanThread() {

        //绑定当前的设备信息
//        ScanDeviceDataService scanDeviceDataService = SpringUtils.getBean(ScanDeviceDataServiceImpl.class);
//        this.device = scanDeviceDataService.getById(100010);
//        this.deviceInfo = deviceInfoService.getById(100010);
        this.start();
    }

    @Override
    public void run() {
        while (true) {
            try {
                //添加一个请求
//                AskData askData1 = new AskData();
//                askData1.setAskId("sss");
//                askData1.setAreaId("7");
//                askData1.setScanType(1);
//                askData1.setType(DeviceEnum.Tanker_Double_Track_2.getDeviceCode());
//                addAskDataQue(askData1);
                Thread.sleep(1000);
//                获取当前的请求列表
                Queue<AskData> tmpAskData = getAskDataQue();

                System.out.println(tmpAskData.toString());
                //假设当前的请求列表有，循环准备开始获取抓点/放点
//                while (!tmpAskData.isEmpty()) {
//                log.info("开始获取槽车放点");
                while (!tmpAskData.isEmpty()) {
                    Integer num = 0;
                    AskData askData = tmpAskData.poll();

                    //读取当前的请求
                    //获取当前请求ID
                    String askId = askData.getAskId();
                    //获取当前的槽车类型
                    String tankerType = askData.getType();

                    Integer craneType = askData.getScanType();

                    tmpAskData.poll();

                    //根据传入的槽车类型设置需要扫描对象
                    ScanDeviceData nowTankerDeviceData = tankerType.equals(DeviceEnum.Tanker_Double_Track_1.getDeviceCode()) ? firstTanker : secondTanker;
                    //根据传入的天车类型选择天车
                    String craneId = craneIdMap.get(craneType);
                    Boolean scanState = false;
                    try {
                        //先获取扫描数据
                        scanState = getScanningData(nowTankerDeviceData);
                        if (scanState) {
                            //获取放点
                            List<Coord> discharges = getDischarge(this.scanningData, nowTankerDeviceData.getDeviceCode(),craneId);
                            System.out.println(discharges);
                            if (!discharges.isEmpty()) {
                                addResponseMap(askId, new PointData(true, "获取放点成功", discharges, new Timestamp(System.currentTimeMillis())));
                                break;
                            } else {
                                addResponseMap(askId, new PointData(false, "获取放点失败"));
                            }

                        }else{
                            log.error("没有找到对应的槽车");
                            addResponseMap(askId, new PointData(false, "没有找到对应的槽车"));
                        }
                    } catch (CustomException e) {
                        e.printStackTrace();
                        addResponseMap(askId, new PointData(false, e.getMsg(), null, new Timestamp(System.currentTimeMillis())));

                    } catch (Exception e) {
                        e.printStackTrace();
                        addResponseMap(askId, new PointData(false, e.getMessage(), null, new Timestamp(System.currentTimeMillis())));
                    }

                    askDataQue.poll();


                }

                Thread.sleep(3000);
                // 线程逻辑代码
            } catch (Exception e) {
                // 捕获线程异常
                e.printStackTrace();
                // 线程挂掉后，等待一段时间再重新启动
                try {
                    Thread.sleep(1000); // 可以根据需要调整等待时间
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    @Override
    public void heartbeat(DeviceSocketClient socketClient) {

        NetSocket socket = socketClient.getSocket();
        System.err.println("【" + device.getDeviceName() + "】首次发送心跳！");
        socket.write(Buffer.buffer("HB"));
        socketClient.getVertx().setPeriodic(1000 * 10, t -> {
            socket.write(Buffer.buffer("HB"));
        });
    }

    public synchronized Queue<AskData> getAskDataQue() {
        return askDataQue;
    }

    public synchronized void addAskDataQue(AskData askData) {
        this.askDataQue.add(askData);
    }

    public synchronized Map<String, PointData> getResponseMap() {
        return responseMap;
    }

    public synchronized void addResponseMap(String askId, PointData pointData) {
        this.responseMap.put(askId, pointData);
    }

    public boolean getScanningData(ScanDeviceData nowScanDeviceData) {
        // 获取同跨天车任务
        setScanningData(null);
        NormalThread normalThread = SpringUtils.getBean(DoubleTrackPZTThread.class);
        ScanningData scanningData = PTZUtils.scanning(nowScanDeviceData, normalThread.getSocketClient());
        try {
            List<Coord> areas = CoordinatesUtils.queryArea(scanningData.getScanningArea(), nowScanDeviceData.getDeviceCode(), scanningData.getScanningDate());
//            List<Coord> areas1 = CoordinatesUtils.queryArea(scanningData.getScanningArea(), DeviceEnum.Tanker_Double_Track_2.getDeviceCode(), scanningData.getScanningDate());
            if (areas.size() < 4) {
//                    normalThread.setStart(false);
                return false;
            }
            List<Coord> dems = CoordinatesUtils.yuntaiScanningHandle(scanningData.getScanningDem());
            CoordinatesUtils.removeShadows(dems);
            if (dems.size() == 0) {
                return false;
            }
            int z = dems.stream().min(new CoordSort(4)).get().getZ();
            if (z < CoordConstant.Tanker_Safe_Height - 1500) {
//                    yuntaiThread.setStart(false);
                return false;
            }
//            boolean b = deviceThread.updateDischarge(sameTask, scanningData);
//            if (!b) {
//                System.out.println("ssss");
////                    yuntaiThread.setStart(false);
//                return false;
//            }
//                deviceThread.setOldTask(new ArrayList<>(sameTask));
        } catch (CustomException e) {
//            System.err.println("【" + device.getDeviceName() + "】" + e.getMsg());
//                yuntaiThread.setStart(false);
            return false;
        } catch (Exception e) {
            e.printStackTrace();
//                yuntaiThread.setStart(false);
            return false;
        }
        setScanningData(scanningData);
//            yuntaiThread.setStart(false);

        CommonUtils.sleep(1000);
        return true;
    }

    public List<Coord> getDischarge(ScanningData scanningData, String deviceCode,String craneCode) {
        LambdaQueryWrapper<UfcDeviceInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UfcDeviceInfo::getDeviceOid, deviceCodeIdMap.get(deviceCode));
        UfcDeviceInfo ufcDeviceInfo = ufcDeviceInfoService.list(lambdaQueryWrapper).get(0);
        List<Coord> areas = CoordinatesUtils.queryArea(scanningData.getScanningArea(), deviceCode);
        List<Coord> dems = CoordinatesUtils.yuntaiScanningHandle(scanningData.getScanningDem());
        areas.sort(new CoordSort(3));
        int may = areas.get(2).getY();
        int miy = areas.get(1).getY();
        areas.sort(new CoordSort(2));
        int max = areas.get(2).getX();
        int mix = areas.get(1).getX();
//        if (may - ufcDeviceInfo.getWidth() < miy) {
//            this.lock.unlock();
//            throw new CustomException(ExceptionEnum.TANKER_INFO_ERROR);
//        }
        int y = (may + may - ufcDeviceInfo.getWidth()) / 2;
        int x = (max + mix) / 2;
        int tx = ufcDeviceInfo.getLength() / 2;
        int ty = ufcDeviceInfo.getWidth() / 2 - CoordConstant.Tanker_Safe_Distance;
        Coord coord = new Coord(x, y, 0);
        QuadrilateralVertex vertex = CoordinatesUtils.queryVertex(coord, tx, ty);
        List<Coord> screens = CoordinatesUtils.screenDesignationRegion(vertex, dems);
        //去除阴影
        CoordinatesUtils.removeShadows(screens);

        //查询天车信息
        LambdaQueryWrapper<UfcDeviceInfo> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UfcDeviceInfo::getDeviceOid, craneCode);
        UfcDeviceInfo ufcDeviceInfo1 = ufcDeviceInfoService.list(lambdaQueryWrapper1).get(0);


        // 查询物料信息
        int type = Integer.parseInt(this.getSpan()) / 100;
        // 一号先卸
        Coord discharge1 = CoordinatesUtils.dischargeCoord(new ArrayList<>(screens), vertex, ufcDeviceInfo1.getLength(), ufcDeviceInfo1.getWidth(), false);
        Coord discharge2 = CoordinatesUtils.dischargeCoord(new ArrayList<>(screens), vertex, ufcDeviceInfo1.getLength(), ufcDeviceInfo1.getWidth(), false);
        Coord discharge3 = CoordinatesUtils.dischargeCoord(new ArrayList<>(screens), vertex, ufcDeviceInfo1.getLength(), ufcDeviceInfo1.getWidth(), false);
        Coord discharge4 = CoordinatesUtils.dischargeCoord(new ArrayList<>(screens), vertex, ufcDeviceInfo1.getLength(), ufcDeviceInfo1.getWidth(), false);
//        System.err.println("【" + device.getDeviceName() + "】本次四个放料点如下：");
//        System.err.println("【" + device.getDeviceName() + "】一号先卸：" + discharge1);
//        System.err.println("【" + device.getDeviceName() + "】二号后卸：" + discharge2);
//        System.err.println("【" + device.getDeviceName() + "】二号先卸：" + discharge3);
//        System.err.println("【" + device.getDeviceName() + "】一号后卸：" + discharge4);
        return new ArrayList<Coord>() {{
            add(discharge1);
            add(discharge2);
            add(discharge3);
            add(discharge4);
        }};
    }

    private void takeCenter(Coord coord, int center) {
        if (coord != null) {
            coord.setX(center);
        }
    }


}
